(function($){
	var KEY = "jforest.tree";
	
	var TreeNode = function(options){
		this.options = $.extend({
			isLast:true,
			isLeaf:true,
			isRoot:false,
			loadData:function(){},
			click:function(){}
		},options);
		var opts = this.options,node = this;
		this.$el = $('<li><span class="button"></span><a href="javascript:void(0);"><i class="fa fa-folder"></i>'+opts.name+'</a></li>');
		this.$el.find('>a').click(function(){opts.click.apply(node);});
		if(opts.isRoot==true){
			this.$el.find('>span:first').addClass('root-close').click(function(){
				node._toggle(this,'root-open','root-close');
			});
		}else if(opts.isLeaf==true){
			jf.replaceClass(this.$el.find('>a>i'),'fa-folder','fa-file');
			if(opts.isLast==true){
				this.$el.find('>span:first').addClass('bottom-line');
			}else{
				this.$el.find('>span:first').addClass('center-line');
			}
		}else if(opts.isLast==true){
			this.$el.find('>span:first').addClass('bottom-close').click(function(){
				node._toggle(this,'bottom-open','bottom-close');
			});
		}else{
			this.$el.find('>span:first').addClass('center-close').click(function(){
				node._toggle(this,'center-open','center-close');
			});
		}
	}

	TreeNode.prototype = {
		_createChildEl:function(){
			if(this.$el.find('>ul').length==0){
				if(this.options.isLast==false){
					this.$el.append('<ul class="line" style="display:none;"></ul>');
				}else{
					this.$el.append('<ul style="display:none;"></ul>');
				}
			}
			return this.$el.find('>ul');
		},
		_toggle:function(spanEl,openClass,closeClass){
			var opts = this.options,node = this;
			if($(spanEl).hasClass(closeClass)){
				$(spanEl).removeClass(closeClass);
				$(spanEl).addClass(openClass);
				if(node.$el.find('>ul').length==1){
					node.$el.find('>ul').show(300);
				}else{
					opts.loadData.apply(node,[function(){
						node.$el.find('>ul').show(300);
					}]);
				}
			}else{
				$(spanEl).removeClass(openClass);
				$(spanEl).addClass(closeClass);
				node.$el.find('>ul').hide(300);
			}
		},
		close:function(){
			var $spanEl = this.$el.find('>span:first'),opts = this.options;
			node.$el.find('>ul').hide(300);
			if(opts.isLeaf == false){
				if(opts.isRoot==true){
					$spanEl.removeClass('root-open');
					$spanEl.addClass('root-close');
				}else if(opts.isLast==true){
					$spanEl.removeClass('bottom-open');
					$spanEl.addClass('bottom-close');
				}else{
					$spanEl.removeClass('center-open');
					$spanEl.addClass('center-close');
				}
			}
		},
		open:function(){
			var $spanEl = this.$el.find('>span:first'),opts = this.options,node = this;
			if(node.$el.find('>ul').length==0){
				opts.loadData.apply(node,[function(){
					node.$el.find('>ul').show(300);
				}]);
			}else{
				node.$el.find('>ul').show(300);
			}
			if(opts.isLeaf == false){
				if(opts.isRoot==true){
					$spanEl.removeClass('root-close');
					$spanEl.addClass('root-open');
				}else if(opts.isLast==true){
					$spanEl.removeClass('bottom-close');
					$spanEl.addClass('bottom-open');
				}else{
					$spanEl.removeClass('center-close');
					$spanEl.addClass('center-open');
				}
			}
		}
	}
	
	
	var Tree = function(element,options){
		this.$el = $(element);
		this.options = $.extend({
			ajax:{},
			checkbox:false,
			nodeClick:function(){},
			checkboxClick:function(node,el){},
			root:{id:null,name:'根节点'}
		},options);
		var tree=this;
		this.ajax = jf.getAjax($.extend({},this.options.ajax,{
			bindObj:this,
			param:{},
			callback:function(result){}
		}));
		if(this.options.checkbox == true){
			this.checkbox = new CheckboxPlug();
		}
		this.$el.append('<ul class="jf-tree"></ul>');
		this._initial();
	};

	Tree.prototype = {
		_initial:function(){
			var opts = this.options,tree = this;
			var $childEl = this.$el.find('>ul');
			this.root = tree._addNode($childEl,{
				id:opts.root.id,
				name:opts.root.name,
				isRoot:true,
				isLeaf:false
			});
			if(opts.root.children){
				this.addChildNode(this.root,opts.root.children);
			}
			this.root.open();
			this.root._createChildEl().show();
		},
		_nodeLoadData:function(node,callback){
			var tree = this,opts = this.options;
			if(this.ajax.isValid()){
				var param = {pid:node.options.id};
				if($.isFunction(opts.ajax.param)){
					param = opts.ajax.param.apply(tree,[node]);
				}
				this.ajax.load(param,function(result){
					var data = result;
					if($.isFunction(opts.ajax.callback)){
						data = opts.ajax.callback.apply(tree,[result,node]);
					}
					tree.addChildNode(node,data);
					callback.apply(tree);
				});
			}
		},
		addChildNode:function(node,children){
			var opts = this.options,tree = this;
			if($.isArray(children)){
				var $childEl = node._createChildEl();
				$.each(children,function(i,v){
					var childNode = tree._addNode($childEl,$.extend(v,{
						isLeaf:jf.isNotNull(v.isLeaf)?v.isLeaf:$.isArray(v.children)==false,
						isLast:i==(children.length-1)
					}));
					if(childNode.options.isLeaf==false){
						tree.addChildNode(childNode,v.children);
					}
				})
			}
		},
		_addNode:function($childEl,options){
			var opts = this.options,tree = this;
			var childNode = new TreeNode($.extend({
				loadData:function(callback){
					tree._nodeLoadData(this,callback);
				},
				click:function(){
					opts.nodeClick.apply(tree,[this]);
				}
			},options));
			if(tree.checkbox){
				tree.checkbox.initial(tree,childNode,opts.checkboxClick);
			}
			$childEl.append(childNode.$el);
			return childNode;
		},
		addNode:function(pid,options){
			if(arguments.length==1){
				options = pid;
				pid = null;
			}
			if(pid==null || pid == this.root.options.id){
				var $childEl = this.root._createChildEl();
				return this._addNode($childEl,options);
			}
		},
		refresh:function(){
			this.root.$el.find('>ul').remove();
			this.root.open();
		}
	};
	
	$.fn.jfTree = function(){
		var args = Array.prototype.slice.call(arguments, 0);
		var value = undefined;
		this.each(function () {
			var $this = $(this);
			if (args.length === 0 || typeof(args[0]) === "object") {
				opts = args.length === 0 ? {} : $.extend({}, args[0]);
				$this.data(KEY,new Tree(this,opts)); //创建控件
			}else if (typeof(args[0]) === "string"){
				var entity = $this.data(KEY);
                if(entity === undefined){return;}
                value = entity[args[0]].apply(entity, args.slice(1));
			}else{
				 throw 'Invalid arguments to '+KEY+' plugin: ' + args;
			}
	    });
	    return (value === undefined) ? this : value;
	};
	
	$.fn.jfTree.Constructor = Tree;
	
	var CheckboxPlug = function(){
		Tree.prototype.getCheckdeData = function(){
		}
	}
	
	CheckboxPlug.prototype = {
		initial:function(tree,node,callback){
			var $el = $('<span class="button no"><input type="checkbox" value="'+node.options.id+'"/></span>');
			node.$el.find('>a').before($el);
			$el.find('>input[type="checkbox"]').change(function(){
				if($.isFunction(callback)){
					callback.apply(tree,[node,this]);
				}
			})
		}
	}
})(window.jQuery)